﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using bigormScreensaver;

namespace bigormscreensaver
{
    class Util
    {
        #region WINAPI
        [DllImport("user32.dll")] public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
        [DllImport("user32.dll")] public static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong);
        [DllImport("user32.dll", SetLastError = true)] public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
        [DllImport("user32.dll")] public static extern bool GetClientRect(IntPtr hWnd, out Rectangle lpRect);
        #endregion WINAPI
        public static bool FileCopy(string sSrc, string sDest, bool bAsAdmin, out string sResult)
        {
            bool bRes = true;
            sResult = "success";
            try
            {
                if (bAsAdmin)
                {
                    sSrc = Environment.ExpandEnvironmentVariables(sSrc);
                    sDest = Environment.ExpandEnvironmentVariables(sDest);
                    if (sSrc.IndexOf('"') == -1 && sSrc.IndexOf(' ') > -1)
                        sSrc = "\"" + sSrc + "\"";
                    if (sDest.IndexOf('"') == -1 && sDest.IndexOf(' ') > -1)
                        sDest = "\"" + sDest + "\"";
                    string sParams = sSrc + " " + sDest;
                    ProcessStartInfo psi = new ProcessStartInfo(Environment.ExpandEnvironmentVariables("%windir%\\System32\\cmd"), "/Ccopy /y " + sParams);
                    psi.Verb = "runas";
                    psi.UseShellExecute = true;
                    Process p = Process.Start(psi);
                    p.WaitForExit();
                    if (p.ExitCode != 0)
                    {
                        bRes = false;
                        sResult = p.ExitCode.ToString();
                    }
                }
                else
                    File.Copy(sSrc, sDest, true);
            }
            catch (Exception ex)
            {
                sResult = ex.Message;
                bRes = false;
            }
            return bRes;
        }
        public static void FileDelete(string sDest, bool bAsAdmin, out string sCmdRes)
        {
            sCmdRes = "success";
            try
            {
                if (bAsAdmin)
                {
                    sDest = Environment.ExpandEnvironmentVariables(sDest);
                    if (sDest.IndexOf('"') == 0 && sDest.IndexOf(' ') > 0)
                        sDest = "\"" + sDest + "\"";
                    string sParams = "/Cdel " + sDest;
                    ProcessStartInfo psi = new ProcessStartInfo(Environment.ExpandEnvironmentVariables("%windir%\\System32\\cmd.exe"), sParams);
                    Clipboard.SetText(sParams);
                    psi.Verb = "runas";
                    psi.UseShellExecute = true;
                    Process p = Process.Start(psi);
                    p.WaitForExit();
                    if (p.ExitCode != 0)
                        sCmdRes = p.ExitCode.ToString();
                }
                else
                    File.Delete(sDest);
            }
            catch(Exception ex)
            {
                sCmdRes = ex.Message;
            }
        }
        public static void FileOpenScreensaverSettings()
        {
            try
            {
                ProcessStartInfo psi = new ProcessStartInfo(Environment.ExpandEnvironmentVariables("%windir%\\System32\\control.exe"), "desk.cpl,screensaver,@screensaver");
                psi.Verb = "runas";
                psi.UseShellExecute = true;
                Process p = Process.Start(psi);
            }
            catch (Exception) { }
        }
        public static string File_Executable { get { return Application.ExecutablePath; } }
        public static string File_ScreenserverFilename { get { return "bigorm.scr";/*Path.GetFileNameWithoutExtension(Application.ExecutablePath) + ".scr";*/ } }
        public static string File_Windir { get { return Environment.ExpandEnvironmentVariables("%windir%"); } }
        public static string File_Destination64 { get { return File_Windir + "\\SysWOW64\\" + File_ScreenserverFilename; } }
        public static string File_Destination32 { get { return File_Windir + "\\System32\\" + File_ScreenserverFilename; } }
        public class UTime
        {
            public TimeSpan tsDuration = new TimeSpan(0, 1, 0);
            private string sDuration;
            private UTime() { }
            public UTime(string duration)
            {
                sDuration = duration;
                tsDuration = FromString(duration);
            }
            public static TimeSpan FromString(string duration)
            {
                TimeSpan tsRet = new TimeSpan(0, 1, 0);
                if (!TimeSpan.TryParse(duration, out tsRet))
                {
                    try
                    {
                        if (duration == "instant") //instant
                            tsRet = new TimeSpan();
                        else if (duration.IndexOf("ms") > 0) //ms
                            tsRet = new TimeSpan(0, 0, 0, 0, int.Parse(duration.Remove(duration.Length - 2).Trim()));
                        else if (duration.IndexOf("sec") > 0) //sec
                            tsRet = new TimeSpan(0, 0, int.Parse(duration.Remove(duration.Length - 4).Trim()));
                        else if (duration.IndexOf("min") > 0) //min
                            tsRet = new TimeSpan(0, int.Parse(duration.Remove(duration.Length - 4).Trim()), 0);
                        else if (duration.IndexOf("hour") > 0) //hour/hours
                            tsRet = new TimeSpan(int.Parse(duration.Remove(duration.Length - 5).Trim()), 0, 0);
                        else if (duration.IndexOf("day") > 0) //day/days
                            tsRet = new TimeSpan(int.Parse(duration.Remove(duration.Length - 4).Trim()), 0, 0, 0);
                        else if (duration.IndexOf("week") > 0) //week/weeks
                            tsRet = new TimeSpan(7 * int.Parse(duration.Remove(duration.Length - 5).Trim()), 0, 0, 0);
                        else if (duration.IndexOf("month") > 0) //month/months
                            tsRet = new TimeSpan(30 * int.Parse(duration.Remove(duration.Length - 6).Trim()), 0, 0, 0);
                        else if (duration.IndexOf("year") > 0) //month/months
                            tsRet = new TimeSpan(365 * int.Parse(duration.Remove(duration.Length - 5).Trim()), 0, 0, 0);
                        else if (duration.IndexOf("ever") > 0) //for ever
                            tsRet = TimeSpan.MaxValue;
                        else
                            tsRet = new TimeSpan(0, 1, 0);//Invalid? one minute
                    }
                    catch (Exception ex)
                    {
                        Debug.WriteLine(ex.Message);
                    }
                }
                return tsRet;
            }
            public override string ToString()
            {
                return sDuration;
            }
        }
        private static UTime[] _SelectableTime = null;
        public static UTime[] SelectableTime
        {
            get
            {
                if (_SelectableTime == null)
                    _SelectableTime = new UTime[] 
                    {
                        new UTime("instant")
                        ,new UTime("1ms")
                        ,new UTime("2ms")
                        ,new UTime("4ms")
                        ,new UTime("6ms")
                        ,new UTime("10ms")
                        ,new UTime("20ms")
                        ,new UTime("30ms")
                        ,new UTime("40ms")
                        ,new UTime("60ms")
                        ,new UTime("100ms")
                        ,new UTime("200ms")
                        ,new UTime("300ms")
                        ,new UTime("400ms")
                        ,new UTime("600ms")
                        ,new UTime("1 sec")
                        ,new UTime("2 sec")
                        ,new UTime("3 sec")
                        ,new UTime("4 sec")
                        ,new UTime("6 sec")
                        ,new UTime("10 sec")
                        ,new UTime("20 sec")
                        ,new UTime("30 sec")
                        ,new UTime("40 sec")
                        ,new UTime("1 min")
                        ,new UTime("2 min")
                        ,new UTime("3 min")
                        ,new UTime("4 min")
                        ,new UTime("6 min")
                        ,new UTime("10 min")
                        ,new UTime("20 min")
                        ,new UTime("30 min")
                        ,new UTime("40 min")
                        ,new UTime("1 hour")
                        ,new UTime("2 hours")
                        ,new UTime("3 hours")
                        ,new UTime("4 hours")
                        ,new UTime("6 hours")
                        ,new UTime("10 hours")
                        ,new UTime("18 hours")
                        ,new UTime("1 day")
                        ,new UTime("2 days")
                        ,new UTime("4 days")
                        ,new UTime("1 week")
                        ,new UTime("2 weeks")
                        ,new UTime("1 month")
                        ,new UTime("2 months")
                        ,new UTime("3 months")
                        ,new UTime("1 year")
                        ,new UTime("for ever")
                };
                return _SelectableTime;
            }
        }
        public class HtmlImageUriExtractor
        {
            private class FindStringsInOrder
            {
                private class FindString
                {
                    int iFound;
                    string sFind;
                    int iFindLength;
                    public bool bStoreNonMatching;
                    private StringBuilder sbNonMatching;
                    public FindString(string sFind, bool bStoreNonMatching)
                    {
                        this.sFind = sFind;
                        iFindLength = sFind.Length;
                        iFound = 0;
                        sbNonMatching = new StringBuilder();
                        this.bStoreNonMatching = bStoreNonMatching;
                    }
                    public bool FoundAfterThis(char c)
                    {
                        if (sFind[iFound] == c)
                        {
                            if (++iFound == iFindLength)
                            {
                                iFound = 0;
                                return true;
                            }
                        }
                        else
                        {
                            if (bStoreNonMatching)
                            { // Store
                                if (iFound > 0) // Store what we have missed because we thought it was matching
                                    sbNonMatching.Append(sFind.Substring(0, iFound));
                                sbNonMatching.Append(c);
                            }
                            iFound = 0;
                        }
                        return false;
                    }

                    public string NonMatching()
                    {
                        if (bStoreNonMatching)
                            return sbNonMatching.ToString();
                        return null;
                    }

                    public void Reset()
                    {
                        iFound = 0;
                        if (bStoreNonMatching)
                            sbNonMatching = new StringBuilder();
                    }
                }
                private List<FindString> lFind = new List<FindString>();
                private int iFoundComplete;
                public FindStringsInOrder(string[] slFind)
                {
                    bool bStoreNonmatchingForNext = false;
                    for (int i = 0; i < slFind.Length; i++)
                    {
                        if (slFind[i].Length == 0)
                            bStoreNonmatchingForNext = true;
                        else
                        {
                            lFind.Add(new FindString(slFind[i], bStoreNonmatchingForNext));
                            bStoreNonmatchingForNext = false;
                        }
                    }
                }
                public void Reset()
                {
                    iFoundComplete = 0;
                    foreach (FindString fs in lFind)
                        fs.Reset();
                }
                public bool FoundAllAfterThis(char ch)
                {
                    bool bRes = false;
                    if (lFind[iFoundComplete].FoundAfterThis(ch))
                    { // Next string
                        if (++iFoundComplete == lFind.Count)
                        { // All found
                            iFoundComplete = 0;
                            bRes = true;
                        }
                    }
                    return bRes;
                }
                public string Result()
                {
                    string sRes = null;
                    foreach (FindString fs in lFind)
                    {
                        if (fs.bStoreNonMatching)
                            sRes = fs.NonMatching();
                    }
                    return sRes;
                }
            }
            private StreamReader sr;
            private int iBufferAllocationSize;
            char[] buffer;
            private int iBufferDataSize;
            private int iBufferPosition;
            List<FindStringsInOrder> lFind;
            public HtmlImageUriExtractor(StreamReader sr, int iBufferSize, string[][]llfindStrings)
            {
                this.sr = sr;
                this.iBufferAllocationSize = iBufferSize;
                buffer = new char[iBufferSize];
                iBufferPosition = iBufferSize; // Read next time :)
                lFind = new List<FindStringsInOrder>();
                foreach (string[] lfindStrings in llfindStrings)
                    lFind.Add(new FindStringsInOrder(lfindStrings));
                //lFind.Add(new FindStringsInOrder(new string[] { "imgurl:&quot;", "", "&quot;" }));
                //lFind.Add(new FindStringsInOrder(new string[]{"<img ", "src=\"", "", "\"", ">"}));
            }
            public bool LookForNextUri(out string uri, out bool bFound)
            {
                bool bEndOfContent = false;
                bFound = false;
                uri = null;
                if (iBufferPosition >= iBufferDataSize)
                    try
                    {
                        iBufferDataSize = sr.ReadBlock(buffer, 0, iBufferAllocationSize);
                        iBufferPosition = 0;
                        if (iBufferDataSize == 0)
                            bEndOfContent = true;
                    }
                    catch (Exception ex)
                    {
                        uri = ex.Message;
                        bFound = true;
                        bEndOfContent = true;
                    }
                while (!bEndOfContent && bFound == false && iBufferPosition < iBufferDataSize)
                {
                    foreach (FindStringsInOrder fsio in lFind)
                        if (fsio.FoundAllAfterThis(buffer[iBufferPosition]))
                        {
                            bFound = true;
                            uri = fsio.Result();
                        }
                    if (bFound)
                        foreach (FindStringsInOrder fsio in lFind)
                            fsio.Reset();
                    iBufferPosition++;
                }
                return !bEndOfContent;
            }
        }
    }
}